// 用户管理
// basic/user

package basic

import (
	"api/models"
	"api/src"
	"api/utils"
	"api/utils/MyRedis"
	"errors"
	"fmt"
	"strings"

	"github.com/beego/beego/v2/core/logs"
	b "github.com/beego/beego/v2/server/web"
	"gorm.io/gorm"
)

type UserC struct {
	src.BaseC
}

func (c UserC) Search() {
	c.Read(src.ReadParams{Model: models.User{}, Filter: src.Filter{PageSize: -1}})
}

func (c UserC) Add() {
	c.Create(&models.User{})
}

func (c UserC) Edit() {
	c.Update(models.User{})
}

func (c UserC) Remove() {
	c.Del(models.User{})
}

// Login 后台管理员登录
// user/login
// 请求参数：username=admin,password=16位md5加密
func (c UserC) Login() {
	type UserLogin struct {
		UserName string `gorm:"comment:用户名" valid:"Required; MinSize(4); MaxSize(20);"`
		Password string `gorm:"comment:登录密码" valid:"Required; Length(16);"`
	}
	username := c.GetString("username")
	password := c.GetString("password")
	userLogin := UserLogin{
		UserName: username,
		Password: password,
	}
	errMsg := src.FormValidation(userLogin)
	if errMsg != "" {
		c.ServerJSON(src.Msg{false, errMsg}, 400)
		return
	}

	user := models.User{}
	db := models.Db
	result := db.Where("userName = ?", username).First(&user)
	if result.Error != nil {
		errMsg = result.Error.Error()
		var status uint32 = 500
		isNotFound := errors.Is(result.Error, gorm.ErrRecordNotFound)
		if isNotFound {
			errMsg = "用户名不存在，请检查字母拼写，区分大小写。"
			status = 200
		} else {
			logs.Error("后台管理员登录发生错误：", errMsg)
		}
		c.ServerJSON(src.Msg{false, errMsg}, status)
		return
	}

	if password != user.Password {
		c.ServerJSON(src.Msg{false, "密码不正确"})
		return
	}

	if !user.Status {
		c.ServerJSON(src.Msg{false, "用户已经停用"})
		return
	}

	// 拦截黑名单用户
	value, errMsg := MyRedis.GetData("blackUser_" + utils.ToStr(user.Id))
	if errMsg != "" {
		c.ServerJSON(src.Msg{false, errMsg}, 500)
		return
	}
	if value != "" {
		c.ServerJSON(src.Msg{false, "黑名单用户禁止访问！"}, 403)
		return
	}

	data := map[string]interface{}{}
	data["user"] = user

	// 获取角色数据
	role := models.Role{}
	result = db.First(&role, user.RoleId)
	if result.Error != nil {
		logs.Error("获取角色数据发生错误：", result.Error)
		c.ServerJSON(src.Msg{false, "获取角色数据发生错误：" + result.Error.Error()}, 500)
		return
	}

	// 获取菜单数据
	menuIds := strings.Split(role.Menu, ",")
	menuData := []models.Menu{}
	result = db.Find(&menuData, menuIds)
	if result.Error != nil {
		logs.Error("获取菜单数据发生错误：", result.Error)
		c.ServerJSON(src.Msg{false, "获取菜单数据发生错误：" + result.Error.Error()}, 500)
		return
	}
	data["menu"] = menuData

	// 获取资源数据
	resIds := strings.Split(role.Res, ",")
	resData := []models.Resource{}
	result = db.Find(&resData, resIds)
	if result.Error != nil {
		logs.Error("获取资源数据发生错误：", result.Error)
		c.ServerJSON(src.Msg{false, "获取资源数据发生错误：" + result.Error.Error()}, 500)
		return
	}
	data["res"] = resData

	// 生成访问令牌
	token := utils.RandStr(8, 1)
	key := fmt.Sprintf("admin_user_%d", user.Id)
	lifetime := b.BConfig.WebConfig.Session.SessionGCMaxLifetime
	errMsg = MyRedis.SetData(key, token, lifetime*60*60)
	if errMsg != "" {
		c.ServerJSON(src.Msg{false, "redis设置访问令牌发生错误：" + errMsg}, 500)
		return
	}

	data["token"] = token
	c.ServerJSON(src.Response{true, data})
}

// ChangePassword 修改登录密码
// user/changePassword
// 请求参数：oldPassword=12345,newPassword=67890
func (c UserC) ChangePassword() {
	type PWD struct {
		OldPassword string `gorm:"comment:原密码" valid:"Required; Length(16);"`
		NewPassword string `gorm:"comment:新密码" valid:"Required; Length(16);"`
	}
	oldPassword := c.GetString("oldPassword")
	newPassword := c.GetString("newPassword")
	pwd := PWD{oldPassword, newPassword}
	errMsg := src.FormValidation(pwd)
	if errMsg != "" {
		c.ServerJSON(src.Msg{false, errMsg}, 400)
		return
	}

	user := models.User{}
	db := models.Db
	result := db.First(&user, c.UserId)
	if result.Error != nil {
		logs.Error(result.Error)
		c.ServerJSON(src.Msg{false, result.Error.Error()}, 500)
		return
	}

	if oldPassword != user.Password {
		c.ServerJSON(src.Msg{false, "原密码错误"})
		return
	}

	result = db.Model(&user).Where("id = ?", user.Id).Update("password", newPassword)
	if result.Error != nil {
		logs.Error(result.Error)
		c.ServerJSON(src.Msg{false, "修改密码发生错误：" + result.Error.Error()}, 500)
		return
	}

	c.ServerJSON(src.Msg{true, "密码修改成功"})
}

// RoleSelectData 角色列表框数据
// 返回格式：[{ id: number, name: string }, {...}]
func (c UserC) RoleSelectData() {
	data, errMsg := c.ReadData(src.ReadParams{
		Model:  models.Role{},
		Field:  "id, `name`",
		Sort:   "id",
		Filter: src.Filter{PageSize: -1},
	})
	if errMsg != "" {
		c.ServerJSON(src.Msg{false, errMsg}, 500)
		return
	}

	c.ServerJSON(src.Response{true, data.TableData})
}
